<?php

declare(strict_types=1);

namespace App\CustHub\Mapper;

use App\Common\Model\Region;
use App\CustHub\Model\ChRobot;
use App\CustHub\Model\ChServer;
use Hyperf\Cache\Annotation\Cacheable;
use Hyperf\Config\Annotation\Value;
use Hyperf\Database\Model\Builder;
use Hyperf\Di\Annotation\Inject;
use Mine\Abstracts\AbstractMapper;
use Mine\Annotation\Transaction;
use Mine\MineModel;
use function Hyperf\Collection\collect;

class ChServerMapper extends AbstractMapper
{
    #[Inject]
    protected ChRobot $chRobot;

    #[Value('cache.default.prefix')]
    protected string $prefix;

    #[Inject]
    protected Region $region;

    public function assignModel()
    {
        $this->model = ChServer::class;
    }

    #[Cacheable(prefix: 'ch_server_info',value: '#{id}',ttl: 30 * 60)]
    public function findById(mixed $id): ChServer|\Hyperf\Database\Model\Model|string|Builder|null
    {
        return $this->model::query()
            ->where('id', $id)
            ->first();
    }


    #[Cacheable(prefix: 'ch_server_uri',value: '#{id}',ttl: 30 * 60)]
    public function getUriById(mixed $id)
    {
        return $this->model::query()->where('id', $id)->value('ip');
    }

    public function clearCache(mixed $id): void
    {
        $redis = redis();
        $keyOne = $this->prefix . 'ch_server_info:'.$id;
        $keyTwo = $this->prefix . 'ch_server_uri:'.$id;
        $redis->del([$keyOne,$keyTwo]);
    }

    /**
     * 获取服务器列表
     */
    public function getServerList($params)
    {
        $filters = [
            'id' => '=',
            'name' => 'like',
            'ip' => '=',
            'region' => 'like',
            'status' => '=',
            'type' => '='
        ];

        $query = $this->model::query()
            ->select([
                'id', 'name', 'ip', 'province', 'city', 'count',
                'status', 'max_count', 'login_count', 'type',
                'pro_code', 'city_code'
            ])
            ->orderBy('id', 'desc');

        $query = applyFilters($query, $params, $filters);

        $paginate = $query->paginate((int) ($params['pageSize'] ?? MineModel::PAGE_SIZE));

        // 直接转换数据结构
        $paginate->getCollection()->transform(function ($item) {
            $item->region = [
                'province' => $item->pro_code,
                'city' => $item->city_code
            ];

            return collect($item)->except(['province_code', 'city_code']);
        });

        return $this->setPaginate($paginate);
    }


    /**
     * 检查服务器ip是否已存在.
     */
    public function checkServerIp(string $ip,mixed $id = ''): bool
    {
        return $this->model::query()
            ->when(!empty($id),function ($query) use ($id){
                $query->where('id', '<>', $id);
            })
            ->where('ip', $ip)
            ->exists();
    }

    /**
     * 检查除指定ID外的服务器是否已经使用该ip
     */
    public function checkServerIpExistsExceptId(string $ip, int $id): bool
    {
        return $this->model::query()
            ->where('ip', $ip)
            ->where('id', '!=', $id)
            ->exists();
    }

    /**
     *编辑数据以符合数据库
     *
     * @param $data
     * @return array $data
     */
    public function getRegion($data): array
    {
        $region = $data['region'];
        $pro_code = $region['province'];
        $city_code = $region['city'];

        $province = $this->region::query()->where('code', $pro_code)->value('name');
        $city = $this->region::query()->where('code', $city_code)->value('name');

        $data['pro_code'] = $pro_code;
        $data['city_code'] = $city_code;
        $data['city'] = $city;
        $data['province'] = $province;
        unset($data['region']);

        return $data;
    }

    /**
     * 新增服务器.
     */
    #[Transaction]
    public function save($data): mixed
    {
        $data = $this->getRegion($data);
        $this->filterExecuteAttributes($data);
        $server = $this->model::create($data);
        return $server->id;
    }

    #[Transaction]
    public function update(mixed $id, array $data): bool
    {
        $data = $this->getRegion($data);
        $this->filterExecuteAttributes($data);
        $this->model::query()->where('id', $id)->update($data);
        return true;
    }

    /**
     * 获取使用中的服务器名单.
     */
    public function usedServerIds($ids): array
    {
        return $this->chRobot::query()
            ->whereIn('server_id', $ids)
            ->pluck('server_id')
            ->unique()
            ->values()
            ->toArray();
    }

    /**
     * 删除服务器.
     */
    public function delete(array $ids): bool
    {
        $this->model::query()
            ->whereIn('id', $ids)
            ->delete();
        return true;
    }

    public function getServerDetail($id)
    {
        return $this->model::query()
            ->select(['pro_code', 'city_code'])
            ->where('id', (int)$id)
            ->get();
    }
}